package com.koko.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.koko.constant.FileNameConstant;
import com.koko.constant.MessageConstant;
import com.koko.context.AdminContext;
import com.koko.exception.AccountPermissionInsufficientException;
import com.koko.game.dto.PublisherDTO;
import com.koko.game.dto.PublisherPageQueryDTO;
import com.koko.game.entity.Publisher;
import com.koko.game.vo.CategoryVO;
import com.koko.game.vo.GamePublisherVO;
import com.koko.game.vo.PublisherVO;
import com.koko.mapper.GamePublisherMapper;
import com.koko.mapper.PublisherMapper;
import com.koko.properties.HttpParamsProperties;
import com.koko.properties.HttpPathProperties;
import com.koko.service.PublisherService;
import com.koko.utils.HttpUrlUtil;
import com.koko.utils.IOUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PublisherServiceImpl implements PublisherService {

    @Value("${koko.urlPrefix}")
    private String baseUrl;

    @Value("${koko.path.publisher}")
    private String basePath;

    @Autowired
    private PublisherMapper publisherMapper;

    @Autowired
    private GamePublisherMapper gamePublisherMapper;

    /**
     * 分页查询
     * @param publisherPageQueryDTO
     * @return
     */
    @Override
    public Page<Publisher> pageQuery(PublisherPageQueryDTO publisherPageQueryDTO) {
        PageHelper.startPage(publisherPageQueryDTO.getPage(), publisherPageQueryDTO.getPageSize());
        return publisherMapper.pageQuery(publisherPageQueryDTO);
    }

    /**
     * 新增发行商
     * @param publisherDTO
     */
    @Override
    @Transactional
    public void save(PublisherDTO publisherDTO, MultipartFile imageFile) {
        // 1. 存入数据库
        Publisher publisher = new Publisher();
        // 忽略icon做单独处理
        BeanUtils.copyProperties(publisherDTO, publisher, "icon", "introduction");
        publisher.setIntroduction(FileNameConstant.PUBLISHER_INTRODUCTION);
        publisher.setFollowers(0);
        publisherMapper.insert(publisher);
        publisherDTO.setId(publisher.getId());
        String directoryPath = basePath + publisher.getId() + "/";
        // 2. 创建对应文件夹
        IOUtil.createDirectory(directoryPath); // 以id命名的文件夹
        IOUtil.createDirectory(directoryPath + "/" + FileNameConstant.NEWS_FOLDER_NAME); // 新闻文件夹
        // 3. 创建介绍的txt文件
        IOUtil.createTxtFile(directoryPath, FileNameConstant.PUBLISHER_INTRODUCTION);
        // 4. 将图片存入文件夹
        imageFileHandle(publisherDTO, imageFile);
        // 5. 将文本写入txt文件
        introductionHandle(publisherDTO);
        // 6. 更新icon地址
        publisher.setIcon(publisherDTO.getIcon());
        publisherMapper.update(publisher);
    }

    /**
     * 批量删除发行商
     * @param ids
     */
    @Override
    @Transactional
    public void deleteBatch(List<Long> ids) {
        // 当前管理员权限验证
        adminPermission();
        for (Long id : ids) {
            // 1. 先删除发行商游戏关系表
            gamePublisherMapper.deleteByPublisherId(id);
            // 2. 再删除发行商列表
            publisherMapper.deleteById(id);
            // 3. 删除文件夹
            IOUtil.deleteFileOrDirectory(basePath + id);
        }
    }

    /**
     * 更新发行商
     * @param publisherDTO
     */
    @Override
    @Transactional
    public void update(PublisherDTO publisherDTO, MultipartFile imageFile) {
        // 1. 处理图片文件
        imageFileHandle(publisherDTO, imageFile);
        // 2. 处理介绍字符串
        introductionHandle(publisherDTO);
        // 3. 更行数据
        Publisher publisher = new Publisher();
        BeanUtils.copyProperties(publisherDTO, publisher);
        publisherMapper.update(publisher);
    }

    /**
     * 查询发行商详细信息
     * @param id
     * @return
     */
    @Override
    public Publisher getById(Long id) {
        Publisher publisher = publisherMapper.getById(id);
        return publisher;
    }

    /**
     * 根据gameId查询发行商详细信息
     * @param gameId
     * @return
     */
    @Override
    public Publisher getByGameId(Long gameId) {
        return publisherMapper.getByGameId(gameId);
    }

    @Override
    public GamePublisherVO getPublisherByGameId(Long gameId) {
        Publisher publisher = publisherMapper.getByGameId(gameId);
        GamePublisherVO gamePublisherVO = new GamePublisherVO();
        BeanUtils.copyProperties(publisher, gamePublisherVO);
        gamePublisherVO.setPublisher(publisher.getName());
        return gamePublisherVO;
    }

    @Override
    public List<PublisherVO> getAllPublishers(String name) {
        List<Publisher> publishers = publisherMapper.getAll(name);
        List<PublisherVO> publisherVOList = publishers.stream().map((item) -> {
            PublisherVO publisherVO = new PublisherVO();
            BeanUtils.copyProperties(item, publisherVO);
            publisherVO.setIcon(HttpUrlUtil.imageRequestUrlEncapsulate(
                    baseUrl + HttpPathProperties.GAME_PUBLISHER_ICON_DOWNLOAD,
                    HttpParamsProperties.GAME_PUBLISHER_ICON_ID + publisherVO.getId().toString(),
                    HttpParamsProperties.GAME_PUBLISHER_ICON_NAME + publisherVO.getIcon()
            ));
            return publisherVO;
        }).collect(Collectors.toList());
        return publisherVOList;
    }

    /**
     * 当前管理员权限判断
     * @return
     */
    private Boolean adminPermission() {
        Integer permission = AdminContext.getCurrentStatus();
        if (permission != 0) {
            throw new AccountPermissionInsufficientException(MessageConstant.PERMISSION_INSUFFICIENT);
        }
        return true;
    }

    /**
     * 图片文件处理方法
     * @param publisherDTO
     * @param imageFile
     * @return
     */
    private PublisherDTO imageFileHandle(PublisherDTO publisherDTO, MultipartFile imageFile) {
        // 1. 处理图片，前端传过来有url，就存储图片
        if (publisherDTO.getIcon() != null) {
            if (imageFile == null) {
                // 2.1 没有传图片文件过来 => 图片未更改
                publisherDTO.setIcon(null);
            } else {
                // 2.1 传图片文件过来 => 更新文件夹中的图片信息
                Publisher publisher = this.getById(publisherDTO.getId());
                // 2.1.1 删除原本图片
                IOUtil.deleteFileOrDirectory(basePath + publisherDTO.getId() + "/" + publisher.getIcon());
                // 2.1.2 将图片写入文件夹，并收到图片的文件名
                String icon = null;
                icon = IOUtil.saveFile(imageFile, basePath + publisherDTO.getId() + "/");
                // 2.1.3 将文件名放到publisherDTO实体类中
                publisherDTO.setIcon(icon);
            }
        }
        return publisherDTO;
    }

    /**
     * introduction写入txt文本处理方法
     * @param publisherDTO
     * @return
     */
    private PublisherDTO introductionHandle(PublisherDTO publisherDTO) {
        // 1. 获取Publisher实体
        Publisher publisher = this.getById(publisherDTO.getId());
        // 2. 获取介绍文本，如果为空则使用空字符串
        String introduction = (publisherDTO.getIntroduction() != null) ? publisherDTO.getIntroduction() : "";
        IOUtil.writeStringToTxt(
                introduction,
                basePath + "/" + publisherDTO.getId() + "/" + publisher.getIntroduction());
        publisherDTO.setIntroduction(publisher.getIntroduction());
        return publisherDTO;
    }
}
